/*
 *    Copyright (c) 2018-2025, proj All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * Neither the name of the proj developer nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 * Author: proj
 */
package com.ykht.proj.activity.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ykht.proj.activity.Enum.CardStatusEnum;
import com.ykht.proj.activity.Enum.PlanStatusEnum;
import com.ykht.proj.activity.constant.CardConstant;
import com.ykht.proj.activity.entity.*;
import com.ykht.proj.activity.mapper.VConsumeRecordMapper;
import com.ykht.proj.activity.mapper.VDiscountPlanMapper;
import com.ykht.proj.activity.service.VConsumeRecordService;
import com.ykht.proj.activity.service.VDiscountPlanService;
import com.ykht.proj.activity.service.VInfoService;
import com.ykht.proj.activity.service.VOrderCardShopService;
import com.ykht.proj.activity.vo.CnGroupShopVoReq;
import com.ykht.proj.activity.vo.VConsumeRecordVo;
import com.ykht.proj.admin.api.feign.RemoteUserService;
import com.ykht.proj.admin.api.vo.UserVO;
import com.ykht.proj.common.core.util.R;
import com.ykht.proj.common.security.util.SecurityUtils;
import com.ykht.proj.coupon.Enum.UserTypeEnum;
import com.ykht.proj.coupon.api.feign.*;
import com.ykht.proj.coupon.entity.*;
import com.ykht.proj.coupon.vo.CnShopVo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 核销表（消费记录表）
 *
 * @author csg
 * @date 2021-05-21 14:21:47
 */
@RequiredArgsConstructor
@Slf4j
@Service
public class VConsumeRecordServiceImpl extends ServiceImpl<VConsumeRecordMapper, VConsumeRecord> implements VConsumeRecordService {

	private final VConsumeRecordMapper vConsumeRecordMapper;
	private final VOrderCardShopService vOrderCardShopService;
	private final VDiscountPlanService vDiscountPlanService;
	private final VInfoService vInfoService;
	private final RemoteWaiterExtService remoteWaiterExtService;
	private final RemoteUserService remoteUserService;
	private final RemoteShopService remoteShopService;
	private final RemotePersonService remotePersonService;
	private final RemoteCouponLogService remoteCouponLogService;


	/**
	 * 卡核销记录 分页查询
	 *
	 * @param page             分页
	 * @param vConsumeRecordVo 条件
	 * @return
	 */
	@Override
	public IPage<VConsumeRecordVo> getVConsumeRecordPage(Page page, VConsumeRecordVo vConsumeRecordVo) {
		return vConsumeRecordMapper.getVConsumeRecordPage(page, vConsumeRecordVo);
	}

	/**
	 * B端 卡核销记录 分页查询
	 *
	 * @param page             分页对象
	 * @param vConsumeRecordVo 核销表（消费记录表）
	 * @return
	 */
	@Override
	public IPage<VConsumeRecordVo> getBConsumeRecordPage(Page page, VConsumeRecordVo vConsumeRecordVo) {
		return vConsumeRecordMapper.getBConsumeRecordPage(page, vConsumeRecordVo);
	}

	/**
	 * B端  根据核销ID获取记录详情
	 *
	 * @param id
	 * @return
	 */
	@Override
	public VConsumeRecordVo getByIdConsumeRecord(Long id) {
		VConsumeRecordVo vConsumeRecordVo = vConsumeRecordMapper.getByIdConsumeRecord(id);
		R<Integer> shopCount = vOrderCardShopService.getByInfoIdCountShop(vConsumeRecordVo.getInfoId(),
				vConsumeRecordVo.getPriceType().equals(CardConstant.CARD_PRICE_TYPE_2) ? null : vConsumeRecordVo.getPriceType());
		vConsumeRecordVo.setShopCount(shopCount.getData());
		return vConsumeRecordVo;
	}

	/**
	 * 验证 订单是否合格(卡是否可以使用)
	 *
	 * @param vConsumeRecordVo
	 * @return
	 */
	@Override
	public R verificationOrder(VConsumeRecordVo vConsumeRecordVo) {
		log.info("->获取会员卡信息");
		VInfo info = new VInfo().selectOne(Wrappers.lambdaQuery(VInfo.class).eq(VInfo::getUseCode, vConsumeRecordVo.getUseCode()));
		if (null == info){
			return R.failed("不正确核销码");
		}
		if (info.getStatus().equals(CardConstant.INFO_STATUS_YDH)) {
			return R.failed("不可用，此卡已过期");
		}
		Integer userType = SecurityUtils.getUser().getUserType();
		Long shopId = null;
		Long brandId = null;
		if (UserTypeEnum.WAITER.getValue().equals(userType)){
			FxWaiterExt userExt = remoteWaiterExtService.getUserExt();
			if (null == userExt){
				return R.failed("当前账号没有绑定的门店");
			}
			shopId = userExt.getShopId();
			brandId = userExt.getBrandId();
		} else {
			CnShop shop = remoteShopService.getByLoginIdShop();
			if (null == shop) {
				return R.failed("当前账号没有绑定的门店");
			}
			shopId = shop.getId();
			brandId = shop.getBrandId();
		}
		log.info("->获取卡信息");
		VCard card = new VCard().selectById(info.getCardId());
		List<Long> shopIdList = new ArrayList<>();
		log.info("->获取卡可以使用的门店列表");
		if (card.getDiscountType().equals(CardConstant.DISCOUNT_TYPE_QB)){
			log.info("->获取卡（全部享用）的门店；列表");
			List<VCardGroup> cardGroupList = new VCardGroup().selectList(
					Wrappers.lambdaQuery(VCardGroup.class).eq(VCardGroup::getCardId, card.getId()));
			List<Long> groupIdList = cardGroupList.stream().map(VCardGroup::getGroupId).collect(Collectors.toList());
			// 根据群组ID集合 获取门店ID集合
			List<VGroupShop> shopIds = new VGroupShop().selectList(
					Wrappers.lambdaQuery(VGroupShop.class).in(VGroupShop::getGroupId, groupIdList));
			shopIdList = shopIds.stream().map(VGroupShop::getShopId).collect(Collectors.toList());
		} else {
			log.info("->获取卡（部分享用）的门店；列表");
			List<VOrderCardShop> vOrderCardShops = new VOrderCardShop().selectList(Wrappers.lambdaQuery
					(VOrderCardShop.class).eq(VOrderCardShop::getOrderCardId, info.getOrderCardId()));
			if (null != vOrderCardShops && vOrderCardShops.size() > 0){
				shopIdList = vOrderCardShops.stream().map(VOrderCardShop::getShopId).collect(Collectors.toList());
			}
		}
		log.info("->验证此卡是否有该门店");
		if (null == shopIdList || shopIdList.size() == 0 || !shopIdList.contains(shopId)) {
			return R.failed("不可用，此卡在本门店不可用");
		}
		log.info("->获取该门店当前的优惠方案列表");
		CnGroupShopVoReq cnGroupShopVoReq = new CnGroupShopVoReq();
		cnGroupShopVoReq.setPlanType(card.getPriceType().equals(CardConstant.CARD_PRICE_TYPE_2) ? null : card.getPriceType());
		List<Long> jdks = new ArrayList<>();
		jdks.add(shopId);
		cnGroupShopVoReq.setPlanStatus(PlanStatusEnum.AT_WORK.getValue());
		cnGroupShopVoReq.setShopIdList(jdks);
		Page page = new Page();
		page.setSize(100);
		Page<CnGroupShopVoReq> groupShopVoReqList = vDiscountPlanService.getByGroupShop(page, cnGroupShopVoReq);
		if (null == groupShopVoReqList || groupShopVoReqList.getRecords().size() == 0){
			return R.failed("不可用，此卡在本门店不可用");
		}
		log.info("->验证此卡在该门店的使用次数是否足够 并获取核销金额");
		// 获取该门店的优惠方案列表
		List<Long> discountPlanIdList = groupShopVoReqList.getRecords().stream().map(CnGroupShopVoReq::getDiscountPlanId).collect(Collectors.toList());
		List<VDiscountPlan> discountPlanList = new VDiscountPlan().selectList(Wrappers.lambdaQuery(VDiscountPlan.class)
				.in(VDiscountPlan::getId, discountPlanIdList)
				.orderByAsc(VDiscountPlan::getDiscount).orderByDesc(VDiscountPlan::getCreateTime));
		BigDecimal payAmount = BigDecimal.ZERO;  // 实际支付金额
		BigDecimal lowMoney = BigDecimal.ZERO;  //  最低消费金额返回信息使用
		BigDecimal lowMoneyBoolean = BigDecimal.ZERO;  //  最低消费金额判断使用
		Integer usageTimesStatus = null;  // 使用次数状态
		Integer surplusUsageTimes = null;  // 剩余使用次数
		for (VDiscountPlan plan : discountPlanList) {
			vConsumeRecordVo.setDiscountPlanId(plan.getId());
			vConsumeRecordVo.setDiscountPlanName(plan.getPlanName());
			vConsumeRecordVo.setUseType(plan.getUseType());
			vConsumeRecordVo.setUseResult(plan.getUseResult());
			vConsumeRecordVo.setApplyRules(plan.getApplyRules());
			vConsumeRecordVo.setApplyPeople(plan.getApplyPeople());
			vConsumeRecordVo.setRebate(plan.getDiscount());
			lowMoney = plan.getLowMoney();
			// 先判断 消费的金额是否 大于等于 最低消费金额
			if (vConsumeRecordVo.getConsumptionAmount().compareTo(plan.getLowMoney()) > -1) {
				// 先计算本次优惠方案 的优惠金额（还是实际支付金额）
				payAmount = vConsumeRecordVo.getConsumptionAmount()
						.multiply(plan.getDiscount()).divide(BigDecimal.valueOf(100));
				lowMoneyBoolean = plan.getLowMoney();
				// 判断该优惠方案是否有使用次数限制
				if (plan.getUsageType().equals(CardConstant.PLAN_USAGE_TYPE_1)) {
					// 判断使用限制是 门店 还是 品牌
					if (plan.getCalculationType().equals(CardConstant.CALCULATION_TYPE_0)) {
						int count = this.count(Wrappers.lambdaQuery(VConsumeRecord.class)
								.eq(VConsumeRecord::getInfoId, info.getId())
								.eq(VConsumeRecord::getShopId, shopId)
								.eq(VConsumeRecord::getDiscountPlanId, plan.getId()));
						// 判断是否还能使用 不能使用 把优惠金额（还是实际支付金额）归零
						surplusUsageTimes = plan.getUsageTimes() - count;
						if (plan.getUsageTimes() <= count) {
							payAmount = BigDecimal.ZERO;
							usageTimesStatus = plan.getUsageTimes();
						}
					} else {
						int count = this.count(Wrappers.lambdaQuery(VConsumeRecord.class)
								.eq(VConsumeRecord::getInfoId, info.getId())
								.eq(VConsumeRecord::getBrandId, brandId)
								.eq(VConsumeRecord::getDiscountPlanId, plan.getId()));
						// 判断是否还能使用 不能使用 把优惠金额（还是实际支付金额）归零
						surplusUsageTimes = plan.getUsageTimes() - count;
						if (plan.getUsageTimes() <= count) {
							payAmount = BigDecimal.ZERO;
							usageTimesStatus = plan.getUsageTimes();
						}
					}
				}
			}
			break;
		}
		if (null != usageTimesStatus){
			return R.failed("不可用，此卡在本店可用的次数已用完");
		}
		// 判断 实际支付金额 是否大于 0
		if (payAmount.compareTo(BigDecimal.ZERO) == 0){
			return R.failed("最低消费金额不足" + lowMoney);
		}
		vConsumeRecordVo.setShopId(shopId);
		vConsumeRecordVo.setBrandId(brandId);
		vConsumeRecordVo.setInfoId(info.getId());
		vConsumeRecordVo.setSurplusUsageTimes(surplusUsageTimes);
		vConsumeRecordVo.setPayAmount(payAmount);
		return R.ok(vConsumeRecordVo);
	}

	/**
	 * 新增核销表（消费记录表）
	 *
	 * @return
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public R addVConsumeRecord(VConsumeRecordVo vConsumeRecordVo) {
		// 再次验证核销次数
		VDiscountPlan discountPlan = vDiscountPlanService.getById(vConsumeRecordVo.getDiscountPlanId());
		if (discountPlan.getUsageType().equals(CardConstant.PLAN_USAGE_TYPE_1)){
			// 判断使用限制是 门店 还是 品牌
			if (discountPlan.getCalculationType().equals(CardConstant.CALCULATION_TYPE_0)) {
				int count = this.count(Wrappers.lambdaQuery(VConsumeRecord.class)
						.eq(VConsumeRecord::getInfoId, vConsumeRecordVo.getInfoId())
						.eq(VConsumeRecord::getShopId, vConsumeRecordVo.getShopId())
						.eq(VConsumeRecord::getDiscountPlanId, discountPlan.getId()));
				if (discountPlan.getUsageTimes() <= count) {
					return R.failed("不可用，此卡在本店可用的次数已用完");
				}
			} else {
				int count = this.count(Wrappers.lambdaQuery(VConsumeRecord.class)
						.eq(VConsumeRecord::getInfoId, vConsumeRecordVo.getInfoId())
						.eq(VConsumeRecord::getBrandId, vConsumeRecordVo.getBrandId())
						.eq(VConsumeRecord::getDiscountPlanId, discountPlan.getId()));
				if (discountPlan.getUsageTimes() <= count) {
					return R.failed("不可用，此卡在本店可用的次数已用完");
				}
			}
		}

		vConsumeRecordVo.setCreateTime(LocalDateTime.now());
		vConsumeRecordVo.setCreateUser(SecurityUtils.getUserId());
		log.info("->给核销数据添加会员卡信息");
		VInfo info = new VInfo().selectOne(Wrappers.lambdaQuery(VInfo.class).eq(VInfo::getUseCode, vConsumeRecordVo.getUseCode()));
		String orderCode = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))+ RandomUtil.randomNumbers(4);
		vConsumeRecordVo.setOrderCode(orderCode);
		vConsumeRecordVo.setInfoId(info.getId());
		vConsumeRecordVo.setInfoCode(info.getVipAccount());
		vConsumeRecordVo.setCardType(info.getCType());
		vConsumeRecordVo.setActivityId(info.getActivityId());
		VOrderCard vOrderCard = new VOrderCard().selectById(info.getOrderCardId());
		vConsumeRecordVo.setActivityRecordId(vOrderCard.getOrderActivityId());
		vConsumeRecordVo.setOrderId(vOrderCard.getOrderId());
		vConsumeRecordVo.setOrderCardId(info.getOrderCardId());
		vConsumeRecordVo.setCardId(info.getCardId());
		if (null != info.getEntId()){
			vConsumeRecordVo.setEntId(info.getEntId());
			VEnt ent = new VEnt().selectById(info.getEntId());
			vConsumeRecordVo.setEntName(ent.getName());
		}
		R<CnPerson> cnPerson = remotePersonService.getPersonById(info.getPersonId());
		vConsumeRecordVo.setPersonId(info.getPersonId());
		vConsumeRecordVo.setPersonName(cnPerson.getData().getNickName());
		vConsumeRecordVo.setPersonPhone(cnPerson.getData().getPhone());
		log.info("->给核销数据添加核销人类型和核销门店，品牌，公司信息");
		Integer userType = SecurityUtils.getUser().getUserType();
		Long shopId = null;
		UserVO user = remoteUserService.getByIdUser(SecurityUtils.getUserId());
		if (UserTypeEnum.WAITER.getValue().equals(userType)){
			FxWaiterExt userExt = remoteWaiterExtService.getUserExt();
			if (null == userExt){
				return R.failed("当前账号没有绑定的门店");
			}
			vConsumeRecordVo.setWaiterId(userExt.getId());
			vConsumeRecordVo.setWaiterName(user.getNickName());
			vConsumeRecordVo.setVerificationType(1);
			shopId = userExt.getShopId();
		} else {
			CnShop shop = remoteShopService.getByLoginIdShop();
			if (null == shop) {
				return R.failed("当前账号没有绑定的门店");
			}
			shopId = shop.getId();
			vConsumeRecordVo.setVerificationType(2);
		}
		CnShopVo shopVo = remoteShopService.getByShopId(shopId);
		vConsumeRecordVo.setShopId(shopVo.getId());
		vConsumeRecordVo.setShopName(shopVo.getName());
		vConsumeRecordVo.setShopLogo(shopVo.getShopLogo());
		vConsumeRecordVo.setBrandId(shopVo.getBrandId());
		vConsumeRecordVo.setBrandName(shopVo.getBrandName());
		vConsumeRecordVo.setCompanyName(shopVo.getCompanyName());
		vConsumeRecordVo.setCompanyId(shopVo.getCompanyId());
		log.info("->查看是不是品牌新客户");
		List<VConsumeRecord> brandTypeList = this.list(Wrappers.lambdaQuery(VConsumeRecord.class)
				.eq(VConsumeRecord::getBrandId, shopVo.getBrandId())
				.eq(VConsumeRecord::getPersonId, info.getPersonId()));
		vConsumeRecordVo.setBrandType(CardConstant.BRAND_TYPE_1);
		vConsumeRecordVo.setShopType(CardConstant.SHOP_TYPE_1);
		CnCouponLog cnCouponLog = new CnCouponLog();
		cnCouponLog.setRecipientId(info.getPersonId());
		if (null == brandTypeList || brandTypeList.size() == 0){
			cnCouponLog.setBrandId(shopVo.getBrandId());
			List<CnCouponLog> brandCustomer = remoteCouponLogService.getBrandShopCustomer(cnCouponLog);
			if (null == brandCustomer || brandCustomer.size() == 0)
				vConsumeRecordVo.setBrandType(CardConstant.BRAND_TYPE_0);
		}
		log.info("->查看是不是门店新客户");
		List<VConsumeRecord> shopTypeList = this.list(Wrappers.lambdaQuery(VConsumeRecord.class)
				.eq(VConsumeRecord::getBrandId, shopVo.getBrandId())
				.eq(VConsumeRecord::getPersonId, info.getPersonId()));
		if (null == shopTypeList || shopTypeList.size() == 0){
			cnCouponLog.setBrandId(null);
			cnCouponLog.setShopId(shopId);
			List<CnCouponLog> shopCustomer = remoteCouponLogService.getBrandShopCustomer(cnCouponLog);
			if (null == shopCustomer || shopCustomer.size() == 0)
				vConsumeRecordVo.setShopType(CardConstant.BRAND_TYPE_0);
		}
		VConsumeRecord consumeRecord = BeanUtil.toBean(vConsumeRecordVo, VConsumeRecord.class);
		boolean save = this.save(consumeRecord);
		info.setTotalMoney(consumeRecord.getConsumptionAmount());
		info.setTotalActMoney(consumeRecord.getPayAmount());
		info.setUpdateTime(LocalDateTime.now());
		info.setUpdateUser(SecurityUtils.getUserId());
		vInfoService.updateInfo(info);
		return R.ok(save);
	}
}
